/*
 * This file is part of the Try! Engine project.
 *
 * Copyright 2010-2011 Emanuele Bertoldi. All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the modified BSD License along with this
 * program. If not, see <http://www.opensource.org/licenses/bsd-license.php>
 */

#include "projectmodellist.h"

using namespace Try;

ProjectModelList::ProjectModelList(QObject* parent)
    :   QAbstractListModel(parent)
{
    QHash<int,QByteArray> rolenames;
    rolenames[ProjectModelList::NameRole] = "name";
    rolenames[ProjectModelList::DescriptionRole] = "description";
    rolenames[ProjectModelList::AuthorRole] = "author";
    this->setRoleNames(rolenames);
}

ProjectModelList::~ProjectModelList()
{
}

int ProjectModelList::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent)

    return m_projects.count();
}

QVariant ProjectModelList::data(const QModelIndex& index, int role) const
{
    if (index.isValid())
    {
        int row = index.row();
        Project* project = m_projects.at(row);

        switch (role)
        {
        case Qt::DisplayRole: // ProjectModelList::NameRole
            return project->name();

        case ProjectModelList::DescriptionRole:
            return project->description();

        case ProjectModelList::AuthorRole:
            return project->author();

        default:
            break;
        }
    }

    return QVariant();
}

Project* ProjectModelList::projectAt(int row) const
{
    if (row < m_projects.count())
        return m_projects.at(row);

    return 0;
}

bool ProjectModelList::addProject(Project* project)
{
    return this->insertProject(m_projects.count(), project);
}

bool ProjectModelList::insertProject(int row, Project* project)
{
    if (project && !m_projects.contains(project))
    {
        if (row < 0)
            row = qMax(0, m_projects.count()-row);

        this->beginInsertRows(QModelIndex(), row, row+1);

        m_projects.insert(row, project);

        QObject::connect(project, SIGNAL(loaded()), this, SLOT(onProjectLoaded()));
        QObject::connect(project, SIGNAL(saved()), this, SLOT(onProjectSaved()));
        QObject::connect(project, SIGNAL(closed()), this, SLOT(onProjectClosed()));
        QObject::connect(project, SIGNAL(changed()), this, SLOT(onProjectChanged()));
        QObject::connect(project, SIGNAL(selectionChanged()), this, SLOT(onProjectSelectionChanged()));

        this->endInsertRows();

        emit projectLoaded(project);

        return true;
    }

    return false;
}

bool ProjectModelList::removeProject(int row)
{
    if (row < 0)
        row = qMax(0, m_projects.count()-row);

    if (row < m_projects.count())
    {
        this->beginRemoveRows(QModelIndex(), row, row+1);

        Project* project = m_projects.takeAt(row);

        QObject::disconnect(project, SIGNAL(loaded()), this, SLOT(onProjectLoaded()));
        QObject::disconnect(project, SIGNAL(saved()), this, SLOT(onProjectSaved()));
        QObject::disconnect(project, SIGNAL(closed()), this, SLOT(onProjectClosed()));
        QObject::disconnect(project, SIGNAL(changed()), this, SLOT(onProjectChanged()));
        QObject::disconnect(project, SIGNAL(selectionChanged()), this, SLOT(onProjectSelectionChanged()));

        this->endRemoveRows();

        return true;
    }

    return false;
}

bool ProjectModelList::removeProject(Project* project)
{  
    if (project && m_projects.contains(project))
        return this->removeProject(m_projects.indexOf(project));

    return false;
}

void ProjectModelList::onProjectLoaded()
{
    emit projectLoaded(qobject_cast<Project*>(this->sender()));
}

void ProjectModelList::onProjectSaved()
{
    emit projectSaved(qobject_cast<Project*>(this->sender()));
}

void ProjectModelList::onProjectClosed()
{
    emit projectClosed(qobject_cast<Project*>(this->sender()));
}

void ProjectModelList::onProjectChanged()
{
    Project* project = qobject_cast<Project*>(this->sender());

    int id = 0;

    for (; id<this->rowCount(); ++id)
        if (this->projectAt(id) == project)
            break;

    emit dataChanged(this->index(id), this->index(id));
    emit projectChanged(project);
}

void ProjectModelList::onProjectSelectionChanged()
{
    emit projectSelectionChanged(qobject_cast<Project*>(this->sender()));
}
